#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "EventLoop.h"
#include "EpollDispatcher.h"
#include "PollDispatcher.h"
#include "SelectDispatcher.h"
#include "TcpConnection.h"
#include "Log.h"

void EventLoop::taskWakeup() // 写数据
{
    const char *msg = "加油加油加油";
    write(m_socketPair[0], msg, strlen(msg));
}

int8_t EventLoop::freeChannel(Channel *channel)
{
    int fd = channel->getSocket();
    auto it = m_channelMap.find(fd);
    if(it != m_channelMap.end())
    {
        m_channelMap.erase(it);
        // 关闭 fd
        close(fd);
        // 释放 channel
        delete channel;
    }
    return 0;
}

int EventLoop::readLocalMessage(void *arg) // 读数据
{
    EventLoop *evLoop = static_cast<EventLoop *>(arg);
    char buff[256];
    read(evLoop->m_socketPair[1], buff, sizeof(buff));
    return 0;
}

int EventLoop::readMessage()
{
    char buff[256];
    read(m_socketPair[1], buff, sizeof(buff));
    return 0;
}

EventLoop::EventLoop(EventLoopModelType type) : EventLoop(type, std::string())
{
}

EventLoop::EventLoop(EventLoopModelType type, const std::string threadName)
{
    m_isRun = false; // 默认没有启动
    m_threadID = std::this_thread::get_id();
    m_threadName = (threadName == std::string()) ? "MainThread" : threadName;
    switch (type)
    {
    case EventLoopModelType::EPOLL:
        m_dispatcher = new EpollDispatcher(this);
        break;
    case EventLoopModelType::POLL:
        m_dispatcher = new PollDispatcher(this);
        break;
    default:
        m_dispatcher = new SelectDispatcher(this);
        break;
    }
    m_channelMap.clear();
    int32_t ret = socketpair(AF_UNIX, SOCK_STREAM, 0, m_socketPair);
    if (ret == -1)
    {
        perror("socketpair error");
        exit(0);
    }
#if 0 // 静态函数作为参数被传递调用

    // 指定规则:evLoop->socketPair[0]发送数据    evLoop->socketPair[1]接收数据
    Channel *channel = new Channel(m_socketPair[1], FDEvent::ReadEvent, readLocalMessage, nullptr, nullptr, (void *)this);
    // 添加到任务队列
#else // 成员函数作为参数被传递调用

    // 绑定 - bind   不推荐 依赖隐式的参数忽略行为,自动会忽略额外的参数 也就是(void *)      调用时obj(arg) 自动变成obj()
    //  auto obj = std::bind(&EventLoop::readMessage, this);

    // Lambda 等效写法
    auto obj = [this](void *)
    { return this->readMessage(); };
    
    Channel *channel = new Channel(m_socketPair[1], FDEvent::ReadEvent, obj, nullptr, nullptr, (void *)this);
    addTask(channel, ElemType::ADD);
#endif
}

EventLoop::~EventLoop()
{
}

int8_t EventLoop::run()
{
    // 比较线程ID是否正常
    if (m_threadID != std::this_thread::get_id())
    {
        perror("evLoopThreadID != threadSelf");
        return -1;
    }
    m_isRun = true;
    while (m_isRun)
    {
        m_dispatcher->dispatch(2); // 2s
        processTask();
    }
    return 0;
}

int8_t EventLoop::eventActive(int32_t fd, int32_t event)
{
    printf("eventActive  m_threadName = %s  fd=%d \n", m_threadName.data(), fd);
    if (fd == -1)
    {
        return -1;
    }
    // 取出channel
    Channel *channel = m_channelMap[fd];
    assert(channel->getSocket() == fd);
    if (event & (int)FDEvent::WriteEvent && channel->writeCallback)
    {
        channel->writeCallback(const_cast<void *>(channel->getArg()));
    }
    if (event & (int)FDEvent::ReadEvent && channel->readCallback)
    {
        channel->readCallback(const_cast<void *>(channel->getArg()));
    }
    return 0;
}

int8_t EventLoop::addTask(Channel *channel, ElemType type)
{
    // 加锁 保护共享资源
    m_mutex.lock();

    // 创建新节点
    ChannelElement *node = new ChannelElement;
    node->channel = channel;
    node->type = type;
    m_taskQ.push(node);
    m_mutex.unlock();

    if (m_threadID == std::this_thread::get_id())
    {
        // 子线程/主线程
        processTask();
    }
    else
    {
        // 主线程 -- 告诉子线程处理任务队列中的任务
        // 1.子线程在工作 2.子线程被阻塞了：select poll epoll(极大概率)
        printf("主线程通过cfd = %d 唤醒子线程\n", m_socketPair[1]);
        taskWakeup();
    }
    return 0;
}

int8_t EventLoop::processTask()
{
    while (!m_taskQ.empty())
    {
        m_mutex.lock();
        struct ChannelElement *task = m_taskQ.front();
        m_taskQ.pop();
        m_mutex.unlock();
        switch (task->type)
        {
        case ElemType::ADD:
            if (add(task->channel) == -1)
            {
                return -1;
            }
            break;
        case ElemType::DELECT:
            if (remove(task->channel) == -1)
            {
                return -1;
            }
            break;
        case ElemType::MODIFY:
            if (modify(task->channel) == -1)
            {
                return -1;
            }
            break;
        }
        delete task;
    }
    return 0;
}

int8_t EventLoop::add(Channel *channel)
{
    int32_t fd = channel->getSocket();
    // 找到fd对应的数组元素位置，并存储
    if (m_channelMap.find(fd) == m_channelMap.end())
    {
        m_channelMap[fd] = channel;
        m_dispatcher->setChannel(channel);
        int ret = m_dispatcher->add();
        return ret;
    }
    return -1;
}

int8_t EventLoop::remove(Channel *channel)
{
    int32_t fd = channel->getSocket();
    if (m_channelMap.find(fd) == m_channelMap.end())
    {
        return -1;
    }
    m_dispatcher->setChannel(channel);
    int32_t ret = m_dispatcher->remove();
    return ret;
}

int8_t EventLoop::modify(Channel *channel)
{
    int32_t fd = channel->getSocket();
    if (m_channelMap.find(fd) == m_channelMap.end())
    {
        return -1;
    }
    m_dispatcher->setChannel(channel);
    int32_t ret = m_dispatcher->modify();
    return ret;
}
